class TopicService {

    boolean transactional = true

    /**
     * 创建新的讨论话题
     */
    Topic createTopic(long userId, Topic topic) {
        def user = User.get(userId)
        if(user) {
            user.addToTopics(topic)
            topic.owner = user
            if(!topic.hasErrors() && topic.save()) {
                return topic
            } else {
                throw new TopicException(message:"创建话题失败",topic:topic)
            }
        } else {
            throw new TopicException(message:"无效的用户")
        }
    }

    /**
     * 根据状态获取话题
     */
    List getTopic(String status, Map params) {
        return Topic.findAllByStatus(status,
            [max:Math.min( params.max ? params.max.toInteger() : 10,  100), offset:params.offset? params.offset.toInteger() : 0])
    }

    Topic addSpeaker(Topic topic, User user) {
        user = User.get(user.id)
        if(topic.limitSpeakerNum <= topic.currentSpeakerNum || topic.status != 'INIT') {
            throw new TopicException(message:"话题[${topic}]已经开始啦",topic: topic)
        }
        
        if(user == topic.owner || user in topic.speakers() || user in topic.viewers()) {
            throw new TopicException(message:"你已经在话题[${topic}]啦",topic: topic)
        }
        topic.currentSpeakerNum++
        if(topic.addSpeaker(user)){
            if(topic.limitSpeakerNum == topic.currentSpeakerNum) {
                topic.status = 'START'
            }
            return topic
        } else {
            throw new TopicException(message:"加入话题${topic}成为发言者失败了",topic: topic)
        }
        
    }

    Topic addViewer(Topic topic, User user) {
        user = User.get(user.id)
        if(user == topic.owner || user in topic.speakers() || user in topic.viewers()) {
            throw new TopicException(message:"你已经在话题[${topic}]啦",topic: topic)
        }
        def date = new Date()
        if(topic.status =="END" || date > topic.endTime) {
            throw new TopicException(message:"话题已经结束啦")
        }
        if(topic.addViewer(user)){
            return topic
        }
        throw new TopicException(message:"加入话题${topic}成为观众失败了",topic: topic)
    }

    Opinion addOpinion(Topic topic, Opinion opinion) {
        def user = opinion.author
        if(topic.status == "INIT") {
            throw new TopicException(message:"话题还没有足够的人，暂时不能发言")
        }
        def date = new Date()
        if(topic.status == "END" || date > topic.endTime) {
            throw new TopicException(message:"话题已经结束啦，不能再发言咯")
        }
        if(user != topic.owner && ! user in topic.speakers() ) {
            throw new TopicException(message:"对不起，你不能在该话题发言")
        }
        if(Opinion.findByTopicAndAuthor(topic, user)) {
            throw new TopicException(message:"你已经在该话题发言过了")
        }
        if(opinion.save() && user.addToOpinions(opinion)){
            return opinion
        } else {
            throw new TopicException(message:"添加观点失败")
        }
    }

    Opinion addComment(Opinion opinion, OpinionComment)
}

class TopicException extends RuntimeException {
    String message
    Topic topic
}

